package com.ffcs.crmd.tsp.server;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Properties;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.PosixParser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ffcs.crmd.tsp.common.constant.LoggerName;
import com.ffcs.crmd.tsp.core.util.MixAll;
import com.ffcs.crmd.tsp.server.application.ApplicationManagerHolder;
import com.ffcs.crmd.tsp.server.config.NettyConfig;
import com.ffcs.crmd.tsp.server.config.SchedulerConfig;
import com.ffcs.crmd.tsp.server.core.DataBaseHandler;
import com.ffcs.crmd.tsp.server.core.QuartzSchedulerHandler;
import com.ffcs.crmd.tsp.server.core.RemotingHandler;
import com.ffcs.crmd.tsp.server.core.SchedulerHandler;
import com.ffcs.crmd.tsp.server.log.ServerLogger;
import com.ffcs.crmd.tsp.server.manager.ClientRemotingManager;
import com.ffcs.crmd.tsp.server.manager.JobProcessManager;
import com.ffcs.crmd.tsp.server.manager.TaskRemotingManager;
import com.ffcs.crmd.tsp.server.util.PublicMethodHelper;
import com.ffcs.crmd.tsp.server.util.SchedulerConfigHelper;

/**
 * 
 * 功能说明:调度启动入口
 *
 * @author ZHONGFUHUA
 * 
 * @since 1.0.0-SNAPSHOT
 *
 */
public class SchedulerStartup {
    
    private static Logger                 log;
    
    private static CommandLine            commandLine;
    
    private static DataBaseHandler        dataBaseHandler;
    
    private static QuartzSchedulerHandler quartzSchedulerHandler;
    
    private static RemotingHandler        remotingHandler;
    
    private static SchedulerHandler       schedulerHandler;
    
    /**
     * 
     * 功能说明:创建初始化所有控制中心
     * 
     * @param args 命令参数
     */
    private static void createController(String[] args) {
        
        try {
            Options options = SchedulerConfigHelper.buildCommandLineOptions(new Options());
            commandLine = SchedulerConfigHelper.parseCommandLine(args, options, new PosixParser());
            
            if (null == commandLine) {
                System.err.println("resolve config properties exception.");
                System.exit(0);
            }
            
            // 初始化配置文件
            NettyConfig nettyConfig = new NettyConfig();
            SchedulerConfig schedulerConfig = new SchedulerConfig();
            
            
            // 打印默认配置
            if (commandLine.hasOption('p')) {
                PublicMethodHelper.printObjectProperties(null, nettyConfig);
                PublicMethodHelper.printObjectProperties(null, schedulerConfig);
                System.exit(0);
            }
            
            // 指定配置文件
            if (commandLine.hasOption('c')) {
                String file = commandLine.getOptionValue('c');
                if (file != null) {
                    InputStream in = new BufferedInputStream(new FileInputStream(file));
                    Properties properties = new Properties();
                    properties.load(in);
                    
                    Properties jdbcProperties = PublicMethodHelper.getProperties(properties, MixAll.TSP_SERVER_JDBC_CONFIG_PREFIX);
                    Properties nettyProperties = PublicMethodHelper.getProperties(properties, MixAll.TSP_SERVER_NETTY_CONFIG_PREFIX);
                    Properties schedulerProperties = PublicMethodHelper.getProperties(properties, MixAll.TSP_SERVER_SCHEDULER_CONFIG_PREFIX);
                    Properties quartzProperties = PublicMethodHelper.getPropertiesQuartz(properties);
                    
                    PublicMethodHelper.properties2Object(nettyProperties, nettyConfig);
                    PublicMethodHelper.properties2Object(schedulerProperties, schedulerConfig);
                    
                    
                    System.out.println("load config properties file ok : " + file);
                    in.close();
                    
                    
                    // 初始化日志
                    System.setProperty(MixAll.TSP_SERVER_OPEN_DEFAULT_LOG, schedulerConfig.getIsOpenDefaultLog());
                    ServerLogger.init(schedulerConfig);
                    log = LoggerFactory.getLogger(LoggerName.ServerLoggerName);
                    
                    
                    JobProcessManager jobProcessManager = new JobProcessManager();
                    ApplicationManagerHolder.register("jobProcessManager", jobProcessManager);
                    TaskRemotingManager taskRemotingManager = new TaskRemotingManager();
                    ApplicationManagerHolder.register("taskRemotingManager", taskRemotingManager);
                    ClientRemotingManager clientRemotingManager = new ClientRemotingManager();
                    ApplicationManagerHolder.register("clientRemotingManager", clientRemotingManager);
                    
                    quartzSchedulerHandler = new QuartzSchedulerHandler(quartzProperties);
                    dataBaseHandler = new DataBaseHandler(jdbcProperties);
                    remotingHandler = new RemotingHandler(nettyConfig);
                    schedulerHandler = new SchedulerHandler(schedulerConfig);
                    
                    schedulerHandler.setQuartzSchedulerHandler(quartzSchedulerHandler);
                    dataBaseHandler.setQuartzSchedulerHandler(quartzSchedulerHandler);
                    schedulerHandler.setRemotingHandler(remotingHandler);
                    schedulerHandler.setDataBaseHandler(dataBaseHandler);
                    remotingHandler.setDataBaseHandler(dataBaseHandler);
                    taskRemotingManager.setRemotingHandler(remotingHandler);
                    taskRemotingManager.setDataBaseHandler(dataBaseHandler);
                } else {
                    System.err.println("please input tsp config file path on start command.");
                    System.exit(0);
                }
            } else {
                System.err.println("please check exist configurate properties file.");
                System.exit(0);
            }
            
            
            Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
                private volatile boolean hasShutdown = false;
                
                @Override
                public void run() {
                    synchronized (this) {
                        if (!this.hasShutdown) {
                            this.hasShutdown = true;
                            try {
                                quartzSchedulerHandler.shutdown();
                                System.out.println("Quartz shutdown ok.");
                                remotingHandler.shutdown();
                                System.out.println("Remoting shutdown ok.");
                                schedulerHandler.shutdown();
                                System.out.println("Scheduler shutdown ok.");
                                dataBaseHandler.shutdown();
                                System.out.println("Datasource shutdown ok.");
                                
                            } catch (Throwable e) {
                                e.printStackTrace();
                                System.exit(-1);
                            }
                        }
                    }
                }
            }, "ShutdownHook"));
        } catch (Throwable e) {
            e.printStackTrace();
            log.error("start init tsp exception:", e);
            System.exit(-1);
        }
    }
    
    public static void main(String[] args) {
        createController(args);
        startScheduler(args);
    }
    
    /**
     * 
     * 功能说明:启动调度
     * 
     * @param args 命令参数
     */
    private static void startScheduler(String[] args) {
        try {
            dataBaseHandler.start();
            System.out.println("Data source start ok.");
            remotingHandler.start();
            System.out.println("Remoting start ok.");
            quartzSchedulerHandler.start();
            System.out.println("Quartz start ok.");
            schedulerHandler.start();
            System.out.println("Scheduler start ok.");
        } catch (Throwable e) {
            e.printStackTrace();
            log.error("start tsp exception:", e);
            System.exit(-1);
        }
    }
    
}
